# -*- coding: utf-8 -*-
# @Time     : 2019/10/1 12:35
# Author    :小公瑾
# Email     :906458734@qq.com
# File      :base.py
# Software  :PyCharm
import time
from datetime import datetime
import allure
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.select import Select
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.remote.webdriver import WebDriver
from library.logger import log
from config.config import SCREENSHOT


class Base:
    '''页面基本action封装

        loc: 元素定位表达式（推荐tuple）
        desc: action描述
        timeout: 超时时间
        frequency: 轮询频率
    '''

    def __init__(self, driver: WebDriver):
        self.driver = driver

    def __save_screenshot(self, desc):
        '''页面截屏保存截图'''
        file_name = SCREENSHOT + "\\{}_{}.png".format(datetime.strftime(datetime.now(), "%Y%m%d%H%M%S%f"), desc)
        self.driver.save_screenshot(file_name)
        with open(file_name, mode='rb') as f:
            file = f.read()
        allure.attach(file, desc, allure.attachment_type.PNG)
        log.warning(f"页面截图文件存储路径：{file_name}")

    def __get_element(self, loc, desc):
        '''获取元素'''
        try:
            ele = self.driver.find_element(*loc)
        except Exception as e:
            log.error(f"获取元素失败，loc：{loc}")
            self.__save_screenshot(desc)
            raise e
        else:
            log.debug(f"成功获取元素，loc：{loc}")
            return ele

    def __get_elements(self, loc, desc):
        '''获取元素组'''
        try:
            ele = self.driver.find_elements(*loc)
        except Exception as e:
            log.error(f"获取元素组失败，loc：{loc}")
            self.__save_screenshot(desc)
            raise e
        else:
            log.debug(f"成功获取元素组，loc：{loc}")
            return ele

    def wait_element_to_be_visible(self, loc, desc, timeout=20, frequency=0.5):
        '''等待元素可见'''
        try:
            start_time = time.time()
            WebDriverWait(self.driver, timeout, frequency).until(EC.visibility_of_element_located(loc))
        except Exception as e:
            log.error(f"元素可见等待失败，loc：{loc}")
            self.__save_screenshot(desc)
            raise e
        else:
            end_time = time.time()
            log.debug(f"等待元素可见，loc：{loc}，等待时间：{round(end_time - start_time, 2)}秒")

    def wait_element_to_be_click(self, loc, desc, timeout=20, frequency=0.5):
        '''等待元素可点击'''
        try:
            start_time = time.time()
            WebDriverWait(self.driver, timeout, frequency).until(EC.element_to_be_clickable(loc))
        except Exception as e:
            log.error(f"元素可点击等待失败，loc：{loc}")
            self.__save_screenshot(desc)
            raise e
        else:
            end_time = time.time()
            log.debug(f"等待元素可点击，loc：{loc}，等待时间：{round(end_time - start_time, 2)}秒")

    def wait_element_to_be_exist(self, loc, desc, timeout=20, frequency=0.5):
        '''等待元素存在'''
        try:
            start_time = time.time()
            WebDriverWait(self.driver, timeout, frequency).until(EC.presence_of_element_located(loc))
        except Exception as e:
            log.error(f"元素存在等待失败，loc：{loc}")
            self.__save_screenshot(desc)
            raise e
        else:
            end_time = time.time()
            log.debug(f"等待元素存在，loc：{loc}，等待时间：{round(end_time - start_time, 2)}秒")

    def input_text(self, text, loc, desc, timeout=60, frequency=0.5):
        '''输入文本内容

            text: 输入的文本内容
        '''
        try:
            self.wait_element_to_be_visible(loc, desc, timeout, frequency)
            self.__get_element(loc, desc).send_keys(text)
        except Exception as e:
            log.error(f"输入文本内容（{text}）失败，action：{desc}")
            self.__save_screenshot(desc)
            raise e
        else:
            log.info(f"成功输入文本内容（{text}），action：{desc}")

    def clear_text(self, loc, desc, timeout=20, frequency=0.5):
        '''清空文本框'''
        try:
            self.wait_element_to_be_click(loc, desc, timeout, frequency)
            self.__get_element(loc, desc).clear()
        except Exception as e:
            log.error("清空文本框失败，action：{desc}")
            self.__save_screenshot(desc)
            raise e
        else:
            log.info(f"成功清空文本框内容，action：{desc}")

    def click_button(self, loc, desc, timeout=60, frequency=0.5):
        '''点击按钮'''
        try:
            self.wait_element_to_be_click(loc, desc, timeout, frequency)
            self.__get_element(loc, desc).click()
        except Exception as e:
            log.error(f"点击按钮失败，loc：{loc}，action：{desc}")
            self.__save_screenshot(desc)
            raise e
        else:
            log.info(f"成功点击按钮，loc：{loc}，action：{desc}")

    def scroll_into_view(self, loc, desc, timeout=20, frequency=0.5):
        '''滚动到指定元素位置'''
        try:
            self.wait_element_to_be_exist(loc, desc, timeout, frequency)
            self.__get_element(loc, desc).location_once_scrolled_into_view
        except Exception as e:
            log.error(f"滚动到指定元素失败，loc：{loc}，action：{desc}")
            self.__save_screenshot(desc)
            raise e
        else:
            log.info(f"成功滚动到指定元素，loc：{loc}，action：{desc}")

    def get_element_text(self, loc, desc, timeout=20, frequency=0.5):
        '''获取元素的文本值'''
        try:
            self.wait_element_to_be_exist(loc, desc, timeout, frequency)
            text = self.__get_element(loc, desc).text
        except Exception as e:
            log.error(f"获取文本失败，loc：{loc}，action：{desc}")
            self.__save_screenshot(desc)
            raise e
        else:
            log.info(f"获取到的元素文本值为：{text}，loc：{loc}，action：{desc}")
            return text

    def get_elements_text(self, loc, desc, timeout=20, frequency=0.5):
        '''获取元素的所有文本值'''
        try:
            self.wait_element_to_be_visible(loc, desc, timeout, frequency)
            all_text = self.__get_elements(loc, desc)
            text_list = [one_text.text for one_text in all_text]
        except Exception as e:
            log.error(f"获取文本列表失败，loc：{loc}，action：{desc}")
            self.__save_screenshot(desc)
            raise e
        else:
            log.info(f"获取到的元素文本值列表为：{text_list}，loc：{loc}，action：{desc}")
            return text_list

    def get_element_attr(self, attr_name, loc, desc, timeout=20, frequency=0.5):
        '''获取元素的属性值

            attr_name: 属性名称
        '''
        try:
            self.wait_element_to_be_exist(loc, desc, timeout, frequency)
            value = self.__get_element(loc, desc).get_attribute(attr_name)
        except Exception as e:
            log.error(f"获取元素的属性值{attr_name}失败，loc：{loc}，action：{desc}")
            self.__save_screenshot(desc)
            raise e
        else:
            log.info(f"获取到元素属性{attr_name}的值为：{value}，loc：{loc}，action：{desc}")
            return value

    def switch_to_frame(self, loc, desc, timeout=20, frequency=0.5):
        '''iframe页面切换'''
        try:
            start_time = time.time()
            WebDriverWait(self.driver, timeout, frequency).until(EC.frame_to_be_available_and_switch_to_it(loc))
        except Exception as e:
            log.error(f"iframe切换失败，loc：{loc}，action：{desc}")
            self.__save_screenshot(desc)
            raise e
        else:
            end_time = time.time()
            log.info(f"iframe切换成功，loc：{loc}，action：{desc}，等待时间：{round(end_time - start_time, 2)}秒")

    def switch_to_default_content(self, desc):
        '''切换iframe到main页面'''
        try:

            self.driver.switch_to.default_content()
        except Exception as e:
            log.error("切换iframe到main页面失败")
            self.__save_screenshot(desc)
            raise e
        else:
            log.info("成功切换iframe到main页面")

    def switch_to_parent(self, desc):
        '''切换iframe到上一层页面'''
        try:
            self.driver.switch_to.parent_frame()
        except Exception as e:
            log.error("切换iframe到上一层页面失败")
            self.__save_screenshot(desc)
            raise e
        else:
            log.info("成功切换iframe到上一层页面")

    def suspend_mouse(self, loc, desc, timeout=20, frequency=0.5):
        '''鼠标悬浮'''
        try:
            self.wait_element_to_be_exist(loc, desc, timeout, frequency)
            ele = self.__get_element(loc, desc)
            ActionChains(self.driver).move_to_element(ele).perform()
        except Exception as e:
            log.error(f"鼠标悬浮失败，loc：{loc}，action：{desc}")
            self.__save_screenshot(desc)
            raise e
        else:
            log.info(f"成功鼠标悬浮，loc：{loc}，action：{desc}")

    def alert_close(self, desc, alert_type='alert', text=None, timeout=20, frequency=0.5):
        '''弹框关闭

            alert_type: 弹框类型（alert/confirm/prompt）
            text: prompt弹框输入的文本
        '''
        try:
            start_time = time.time()
            WebDriverWait(self.driver, timeout, frequency).until(EC.alert_is_present())
            if alert_type in ['alert', 'confirm']:
                self.driver.switch_to.alert.accept()
            elif alert_type == 'prompt':
                self.driver.switch_to.alert.send_keys(text)
                self.driver.switch_to.alert.accept()
            else:
                log.error(f"不支持{alert_type},请确认alert的类型")
        except Exception as e:
            log.error(f"关闭{alert_type}类型的弹框失败，action：{desc}")
            self.__save_screenshot(desc)
            raise e
        else:
            end_time = time.time()
            log.info(f"关闭{alert_type}类型的弹框成功，action：{desc}，等待时间：{round(end_time - start_time, 2)}秒")

    def select_action(self, loc, desc, content, select_type, timeout=20, frequency=0.5):
        '''Select操作

            content: select_by_方法的入参
            select_type: select类型（index/value/text）
        '''
        try:
            self.wait_element_to_be_click(loc, desc, timeout, frequency)
            ele = self.__get_element(loc, desc)
            if select_type == 'index':
                Select(ele).select_by_index(content)
            elif select_type == 'value':
                Select(ele).select_by_value(content)
            elif select_type == 'text':
                Select(ele).select_by_visible_text(content)
            else:
                log.error(f"不支持{select_type},请确认Select的类型")
        except Exception as e:
            log.error(f"下拉选择失败，选择类型：{select_type}，loc：{loc}，action：{desc}")
            self.__save_screenshot(desc)
            raise e
        else:
            log.info(f"下拉选择成功，选择类型：{select_type}，loc：{loc}，action：{desc}")

    def switch_to_windows(self, loc, desc, timeout=20, frequency=0.5):
        '''窗口切换'''
        try:
            cur_handles = self.driver.window_handles  # 获取点击之前的窗口总数
            start_time = time.time()
            self.click_button(loc, desc, timeout, frequency)  # 点击按钮后新的窗口出现
            WebDriverWait(self.driver, timeout, frequency).until(EC.new_window_is_opened(cur_handles))
            wins = self.driver.window_handles  # 再次获取窗口总数
            self.driver.switch_to.window(wins[-1])  # 切换到新的页面
        except Exception as e:
            log.error(f"窗口切换失败，loc：{loc}，action：{desc}")
            self.__save_screenshot(desc)
            raise e
        else:
            end_time = time.time()
            log.info(f"窗口切换成功，action：{desc}，等待时间：{round(end_time - start_time, 2)}秒")
